import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core';
import { WebGLService } from 'src/app/services/webgl.service';

@Component({
    selector: 'color-pick',
    templateUrl: './color-pick.component.html',
    styleUrls: ['./color-pick.component.scss']
})
export class ColorPickComponent implements OnInit, AfterViewInit, OnDestroy {
    // 顶点着色器
    private vertexShaderSource = `
        attribute vec4 a_Position;
        attribute vec4 a_Color;
        varying vec4 v_Color;
        void main () {
            gl_Position = a_Position;
            v_Color = a_Color;
        }  
    `;
    private fragShaderSource = `
        precision mediump float;
        varying vec4 v_Color;
        void main () {
            gl_FragColor = v_Color;
        }
    `;
    private gl: WebGLRenderingContext;
    private GRIDNUM = 256;

    constructor(private webglService: WebGLService) { }
    ngOnInit() { }
    ngAfterViewInit () {
        this.init();
    }
    ngOnDestroy () {}

    private init () {
        const canvas = document.querySelector('#myCanvas') as HTMLCanvasElement;
        this.gl = canvas.getContext('webgl');

        // 初始化 shader
        this.webglService.initShader(this.gl, this.vertexShaderSource, this.fragShaderSource);

        // 初始化 VertexBuffer
        // const n = this.initVertexBuffer(this.gl);

        // 设置背景颜色
        this.gl.clearColor(33.0/255, 33.0/255, 33.0/255, 1.0);
        this.gl.clear(this.gl.COLOR_BUFFER_BIT);


        const n = this.initVertexBuffer(this.gl);
        // 画点
        // this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, n);
    }

    private initVertexBuffer (gl: WebGLRenderingContext) {
        const colors = this.calColor();

        for (let i = 0; i < this.GRIDNUM-1; i++) {
            const points = this.calPoints(colors, i);
            console.log('points: ', points)
            const vertices = new Float32Array(points);
            const n = this.GRIDNUM * 2;    // 点的个数
            const byteLen = vertices.BYTES_PER_ELEMENT;

            // 创建缓冲区对象
            const vertexBuffer = gl.createBuffer();
            
            // 将缓冲区对象绑定到目标
            gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

            // 向缓冲区对象中写入数据
            gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

            const program = this.webglService.getProgramByGLContext(gl);
            const a_Position = gl.getAttribLocation(program, 'a_Position');
            const a_Color = gl.getAttribLocation(program, 'a_Color');

            // 将缓冲区对象分配给 a_Position 变量
            gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 5 * byteLen, 0);
            gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 5 * byteLen, 2 * byteLen);

            // 连接 a_Position 变量与分配给它的缓冲区对象
            gl.enableVertexAttribArray(a_Position);
            gl.enableVertexAttribArray(a_Color);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
        }
    }

    private calColor () {
        const colorPoints: number [][][] = [];
        const p0: number[] = [255, 255, 255, 1];    // 左上角
        const p1: number[] = [255, 0, 0, 1];    // 右上角
        const p2: number[] = [0, 0, 0, 1];      // 左下角
        const p3: number[] = [0, 0, 0, 1];      // 右下角


        for (let i = 0; i < this.GRIDNUM; i++) {
            colorPoints[i] = [];
            for (let j = 0; j < this.GRIDNUM; j++) {
                colorPoints[i][j] = [];
            }
        }

        const GRIDIDX = this.GRIDNUM - 1;
        colorPoints[0][0] = p0;
        colorPoints[0][GRIDIDX] = p1;
        colorPoints[GRIDIDX][0] = p2;
        colorPoints[GRIDIDX][GRIDIDX] = p3;

        for (let j = 0; j < GRIDIDX; j++) {
            for (let k = 0; k < 3; k++) {
                colorPoints[0][j][k] = j / GRIDIDX * (colorPoints[0][GRIDIDX][k] - colorPoints[0][0][k]) + colorPoints[0][0][k];
            }
            colorPoints[0][j][3] = 1;

            colorPoints[GRIDIDX][j] = [0, 0, 0, 1];
        }

        for (let i = 1; i < GRIDIDX; i++) {
            for (let j = 0; j < GRIDIDX; j++) {
                for (let k = 0; k < 3; k++) {
                    colorPoints[i][j][k] = i / GRIDIDX * (colorPoints[GRIDIDX][j][k] - colorPoints[0][j][k]) + colorPoints[0][j][k];
                }
                colorPoints[i][j][3] = 1;
            }
        }
        return colorPoints;
    }

    private calPoints (colorArr: number[][][], i: number) {
        const points: number [] = [];   // 前两位为 位置，后三位为 颜色
            for (let j = 0; j < this.GRIDNUM; j++) {
                const pointJ = this.getPoint(i + 1, j, colorArr);
                const pointI = this.getPoint(i, j, colorArr);
                // tempArr[5] = 1;
                points.push(...pointJ, ...pointI);
            }
        return points;
    }

    private getPoint (i: number, j: number, colorArr: number[][][]) {
        const GRIDIDX = this.GRIDNUM - 1;
        const tempArr: number[] = [];
        tempArr[0] = j / GRIDIDX - 0.5;
        tempArr[1] = 0.5 - i / GRIDIDX;
        tempArr[2] = colorArr[i][j][0] / GRIDIDX / 1.0;
        tempArr[3] = colorArr[i][j][1] / GRIDIDX / 1.0;
        tempArr[4] = colorArr[i][j][2] / GRIDIDX / 1.0;
        for (let k = 2; k < 5; k++) {
            if (Number.isNaN(tempArr[k])) tempArr[k] = 0;
        }
        return tempArr;
    }
}